from PySide2.QtCore import *
from PySide2.QtWidgets import *
from PySide2.QtGui import *
from math import sin
from Widgets import Label, Slider, blueStyle, darkStyle
import os, codecs, json


class previewLabel(QLabel):
    click = Signal()

    def __init__(self, text='', parent=None):
        super().__init__(parent)
        self.setText(text)
        self.setAlignment(Qt.AlignCenter)

    def mousePressEvent(self, QEvent):
        self.click.emit()


class OptionWidget(QWidget):  # 调节页
    config = Signal(list)
    closeSignal = Signal()

    def __init__(self, screenList, args=[100, 128, 15, 15, 64, False, 0, 'utils/pikaqiu.png']):
        super(OptionWidget, self).__init__()
        self.setAcceptDrops(True)
        self.args = args
        self.setWindowTitle('鼠标挂坠')
        self.resize(573, 361)

        layout = QGridLayout(self)
        layout.addWidget(Label('开关'), 0, 0, 1, 2)
        self.enableButton = QPushButton()
        self.enableButton.clicked.connect(self.setEnable)
        self.enableButton.setFixedHeight(30)
        layout.addWidget(self.enableButton, 0, 2, 1, 4)
        layout.addWidget(Label('区域'), 1, 0, 1, 2)
        screenTexts = ['显示器 %s  %s x %s' % (cnt + 1, i[2], i[3]) for cnt, i in enumerate(screenList)]
        self.screenSelectCombox = QComboBox()
        self.screenSelectCombox.addItems(screenTexts)
        self.screenSelectCombox.setCurrentIndex(args[6])
        self.screenSelectCombox.currentIndexChanged.connect(self.setScreen)
        layout.addWidget(self.screenSelectCombox, 1, 2, 1, 4)
        self.setEnable()
        layout.addWidget(Label('透明'), 2, 0, 1, 2)
        self.opacitySlider = Slider(10, 100)
        self.opacitySlider.setValue(args[0])
        self.opacitySlider.currentValue.connect(self.setOpacity)
        layout.addWidget(self.opacitySlider, 2, 2, 1, 4)
        layout.addWidget(Label('缩放'), 3, 0, 1, 2)
        self.scaleSlider = Slider(32, 512)
        self.scaleSlider.setValue(args[1])
        self.scaleSlider.currentValue.connect(self.setScale)
        layout.addWidget(self.scaleSlider, 3, 2, 1, 4)
        layout.addWidget(Label('频率'), 4, 0, 1, 2)
        self.freqSlider = Slider(0, 300)
        self.freqSlider.setValue(args[2])
        self.freqSlider.currentValue.connect(self.setFreq)
        layout.addWidget(self.freqSlider, 4, 2, 1, 4)
        layout.addWidget(Label('幅度'), 5, 0, 1, 2)
        self.rangeSlider = Slider(5, 180)
        self.rangeSlider.setValue(args[3])
        self.rangeSlider.currentValue.connect(self.setRange)
        layout.addWidget(self.rangeSlider, 5, 2, 1, 4)
        layout.addWidget(Label('距离'), 6, 0, 1, 2)
        self.distanceSlider = Slider(5, 300)
        self.distanceSlider.setValue(args[4])
        self.distanceSlider.currentValue.connect(self.setDistance)
        layout.addWidget(self.distanceSlider, 6, 2, 1, 4)
        layout.addWidget(QLabel(), 0, 6, 1, 1)
        self.preview = previewLabel('点击或拖入要播放的答谢gif动图')
        self.preview.setFrameShape(QFrame.Box)
        self.preview.setStyleSheet('border:2px dotted #cfcfd0')
        self.preview.setFixedSize(300, 300)
        self.preview.click.connect(self.setPath)
        if args[-1]:
            self.setPath(args[-1])
        layout.addWidget(self.preview, 0, 7, 7, 6)

    def dragEnterEvent(self, QDragEnterEvent):
        QDragEnterEvent.accept()

    def dropEvent(self, QEvent):
        if QEvent.mimeData().hasUrls:
            imgPath = QEvent.mimeData().urls()[0].toLocalFile()
            for s in ['.jpg', '.png', '.bmp', 'gif']:
                if imgPath.endswith(s):
                    self.setPath(imgPath)
                    break

    def setEnable(self):
        self.args[5] = not self.args[5]
        if self.args[5]:
            self.enableButton.setText('停止')
            self.enableButton.setStyleSheet(blueStyle)
        else:
            self.enableButton.setText('开启')
            self.enableButton.setStyleSheet(darkStyle)
        self.sendArgs()

    def setScreen(self, index):
        self.args[6] = index
        self.sendArgs()

    def setOpacity(self, value):
        self.args[0] = value
        self.sendArgs()

    def setScale(self, value):
        self.args[1] = value
        self.sendArgs()

    def setFreq(self, value):
        self.args[2] = value
        self.sendArgs()

    def setRange(self, value):
        self.args[3] = value
        self.sendArgs()

    def setDistance(self, value):
        self.args[4] = value
        self.sendArgs()

    def setPath(self, imgPath=''):
        if not imgPath:
            imgPath = QFileDialog.getOpenFileName(self, "请选择图片文件", '图片', "*jpg *png *bmp *gif")[0]
        if imgPath and os.path.exists(imgPath):
            pixmap = QPixmap(imgPath)
            w, h = pixmap.width(), pixmap.height()
            if w > h:
                pixmap = pixmap.scaled(300, 300 * h / w, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
            else:
                pixmap = pixmap.scaled(300 * w / h, 300, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
            self.preview.setPixmap(pixmap)
            self.args[-1] = imgPath
            self.sendArgs()

    def sendArgs(self):
        self.config.emit(self.args)

    def closeEvent(self, QCloseEvent):
        self.closeSignal.emit()


class Pendant(QWidget):
    def __init__(self, screenList, config, independent=False):
        super(Pendant, self).__init__()
        if config[6] >= len(screenList):
            config[6] = 0
        self.x, self.y, w, h = screenList[config[6]]
        self.move(self.x, self.y)
        self.resize(w, h)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint)
        self.screenList = screenList
        self.config = config
        self.independent = independent
        self.stamp = ''
        self.stampPath = config[-1]
        self.T = 0  # 起始度数
        self.opacity = 100  # 透明度
        self.scale = 128  # 横向缩放宽度
        self.freq = 0.015  # 摆动频率 越高越快
        self.range = 15  # 摆动幅度 越高越大
        self.distance = 64  # 摆锤距离
        self.option = OptionWidget(screenList, config)
        self.option.config.connect(self.setConfig)
        self.option.closeSignal.connect(self.handleClose)
        self.setStamp(config[-1])
        self.setConfig(config)
        self.rotateTimer = QTimer()
        self.rotateTimer.timeout.connect(self.update)
        self.rotateTimer.start(15)

    def setStamp(self, stampPath):
        if stampPath and os.path.exists(stampPath):
            stamp = QPixmap(stampPath)
            w, h = stamp.width(), stamp.height()
            self.h = self.scale * h / w
            self.stamp = stamp.scaled(self.scale, self.h, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)

    def setConfig(self, args):
        self.config = args
        self.opacity, self.scale, self.freq, self.range, self.distance, self.enabled, self.number, self.stampPath = args
        if self.enabled:
            self.show()
        else:
            self.hide()
        self.x, self.y, w, h = self.screenList[self.number]
        self.move(self.x, self.y)
        self.resize(w, h)
        self.freq /= 1000
        self.setWindowOpacity(self.opacity / 100)
        self.setStamp(self.stampPath)

    def paintEvent(self, QPaintEvent):
        if self.stamp:
            self.T += self.freq
            angle = self.range * sin(self.T)
            pos = QCursor.pos()
            x, y = pos.x() - self.x, pos.y() - self.y
            painter = QPainter(self)
            painter.setRenderHints(QPainter.SmoothPixmapTransform)
            painter.translate(x, y)
            painter.rotate(angle)
            painter.translate(-x, -y)
            painter.drawPixmap(x - self.scale / 2, y + self.distance, self.stamp)

    def handleClose(self):
        if self.independent:
            config = {'pendantConfig': self.config}
            with codecs.open('utils/config.json', 'w', 'utf8') as f:  # 保存设置到本地
                f.write(json.dumps(config, ensure_ascii=False))
            self.close()


if __name__ == '__main__':
    app = QApplication([])
    screenNumber = len(app.screens())
    desktop = QApplication.desktop()
    screenList = []
    for num in range(screenNumber):
        rect = desktop.availableGeometry(num)
        screenList.append([rect.left(), rect.top(), rect.width(), rect.height()])
    app.setStyleSheet(open('utils/qdark.qss', 'r').read())
    config = {
        'pendantConfig': [100, 128, 15, 15, 64, True, 0, 'utils/pikaqiu.png']
    }
    if os.path.exists('utils/config.json'):
        with codecs.open('utils/config.json', 'r', 'utf8') as f:
            f = json.loads(f.read())
        config.update(f)  # 用本地配置覆盖默认设置
    config['pendantConfig'][5] = not config['pendantConfig'][5]
    mainWindow = Pendant(screenList, config['pendantConfig'], True)
    mainWindow.option.show()
    # mainWindow.move(160, 90)
    if config['pendantConfig'][5]:
        mainWindow.show()
    else:
        mainWindow.hide()
    app.exec_()
